home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-03-15 | 29.1 KB | 785 lines | [TEXT/gamI] |
- ; ----------------------------------------------------------------------------
- ; File: array.scm
- ; Description: Array creation, manipulation functions.
- ; Author: Raymond Laning at ART
- ; Created: 28-Apr-93
- ; Modified: 07-Dec-93 23:18:51 Raymond Laning
- ; Language: Scheme
- ; Status: Experimental (Use at your own risk)
- ;
- ; (c) Copyright 1993, Advanced Robotic Technologies, Inc.
- ; All Rights Reserved.
- ;
- ; ----------------------------------------------------------------------------
-
- ;;;make-array makes an array of nxmx... entries where n is the row,
- ;;;m is the column, ... and so on - the last entry is the cell init value
- ;;;Example: (make-array 3 4 "foo") makes a 3x4 array of "foo" entries
- (define (make-array . args)
- (let* ((g1 (gensym))
- (len (length args))
- (dims (butlast args))
- (vec (make-vector (apply * dims) (list-ref args (- len 1)))))
- (put g1 'rank (- len 1))
- (put g1 'dims dims)
- (put g1 'vec vec)
- (put g1 'offsets (make-vector (- len 1) 0))
- (put g1 'newdims dims)
- g1))
-
- ;;;make-partition takes an existing array and lists of offsets
- ;;;(offsets are beginning and ending indices)
- ;;;and creates a pointer to the same data but with different
- ;;;dimensions (possibly different rank!)
- (define (make-partition . args)
- (let* ((g1 (gensym))
- (array (car args))
- (previous-offsets (get array 'offsets))
- (offset-list (cdr args))
- (new-rank (length offset-list))
- (vec (get array 'vec))
- (oldims (get array 'dims)))
- (put g1 'vec vec)
- (put g1 'rank new-rank)
- (put g1 'dims oldims)
- (do ((offs offset-list (cdr offs))
- (i 0 (+ i 1))
- (newdims (list))
- (newoffs (make-vector new-rank 0)))
- ((null? offs) (put g1 'offsets newoffs)
- (put g1 'newdims (reverse newdims)))
- (cond ((< (+ (cadar offs) (vector-ref previous-offsets i))
- (list-ref oldims i))
- (vector-set! newoffs i (+ (caar offs)
- (vector-ref previous-offsets i)))
- (set! newdims (cons (- (cadar offs) (caar offs) -1) newdims)))
- (#t (error "Bad partition dims:" offset-list oldims))))
- g1))
-
- ;;;copy partition makes a new array of dimensions (arg2-arg1)x(arg3-arg4)x...
- ;;;the partition should be of the same rank as the source
- (define (copy-partition . args)
- (let* ((source (car args))
- (limits (cdr args))
- (dimensions (get source 'newdims))
- (maxrow (car dimensions))
- (newdims (map (lambda (argls) (- (cadr argls) (car argls) -1)) limits))
- (rank (length newdims))
- (dest (apply make-array (append newdims (list 0.0)))))
- (case rank
- ((0) (array-set! dest 0 (array-ref source 0)))
- ((1) (do ((i 0 (+ i 1))
- (sourcei (caar limits) (+ 1 sourcei)))
- ((> sourcei (cadar limits)))
- (array-set! dest i (array-ref source (modulo sourcei maxrow)))))
- ((2) (do ((i 0 (+ i 1))
- (sourcei (caar limits) (+ 1 sourcei)))
- ((> sourcei (cadar limits)))
- (do ((j 0 (+ j 1))
- (sourcej (caadr limits) (+ 1 sourcej)))
- ((> sourcej (cadadr limits)))
- (array-set! dest i j (array-ref
- source (modulo sourcei maxrow) sourcej)))))
- ((3) (do ((i 0 (+ i 1))
- (sourcei (caar limits) (+ 1 sourcei)))
- ((> sourcei (cadar limits)))
- (do ((j 0 (+ j 1))
- (sourcej (caadr limits) (+ 1 sourcej)))
- ((> sourcej (cadadr limits)))
- (do ((k 0 (+ k 1))
- (sourcek (caar (cddr limits)) (+ 1 sourcek)))
- ((> sourcek (cadar (cddr limits))))
- (array-set! dest i j k
- (array-ref
- source (modulo sourcei maxrow) sourcej sourcek))))))
- (else (error "copy-partition doesn't do rank:" rank)))
- dest))
-
- (define (copy-partition-homogeneous source lim1 lim2)
- (let* ((dimensions (get source 'newdims))
- (maxrow (car dimensions))
- (newdim2 (- (cadr lim2) (car lim2) -1))
- (dest (make-array (- (cadr lim1) (car lim1)) newdim2 1.0)))
- (do ((i 0 (+ i 1))
- (sourcei (car lim1) (+ 1 sourcei)))
- ((>= sourcei (cadr lim1)) dest)
- (do ((j 0 (+ j 1))
- (sourcej (car lim2) (+ 1 sourcej)))
- ((> sourcej (cadr lim2)))
- (array-set! dest i j (array-ref
- source (modulo sourcei maxrow) sourcej))))))
-
- ;;;Array ref takes an array and the rows,columnsl,... and returns
- ;;;the values of that cell
- (define (array-ref . args)
- (let* ((array (car args))
- (refs (cdr args))
- (dimensions (get array 'dims))
- (dims-to-use (get array 'newdims))
- (offsets (get array 'offsets))
- (rank (get array 'rank)))
- (cond ((and (= (length refs) rank)
- (do ((dims dims-to-use (cdr dims))
- (rfs refs (cdr rfs))
- (ok #t))
- ((or (not ok) (null? dims)) ok)
- (if (> (car rfs) (- (car dims) 1)) (set! ok #f) #t)))
- (do ((i (- rank 1) (- i 1))
- (j 0 (+ j 1))
- (product 1)
- (index 0))
- ((< i 0) (vector-ref (get array 'vec) index))
- (set! index (+ index (* (+ (vector-ref offsets i)
- (list-ref refs i))
- product)))
- (set! product (* product (list-ref dimensions i)))))
- ((= (length refs) rank)
- (error "Array subscript out of bounds:" refs dims-to-use))
- (#t (error "Array reference not same rank as array:" refs rank)))))
-
- ;;;array-set! is like array-ref: given an array, the cell row,column...
- ;;;and a value, that cell is set to that value
- (define (array-set! . args)
- (let* ((array (car args))
- (val (list-ref args (- (length args) 1)))
- (refs (butlast (cdr args)))
- (dimensions (get array 'dims))
- (rank (get array 'rank)))
- (cond ((and (= (length refs) rank)
- (do ((dims dimensions (cdr dims))
- (rfs refs (cdr rfs))
- (ok #t))
- ((or (not ok) (null? dims)) ok)
- (if (> (car rfs) (- (car dims) 1)) (set! ok #f) #t)))
- (do ((i (- rank 1) (- i 1))
- (j 0 (+ j 1))
- (product 1)
- (index 0))
- ((< i 0) (vector-set! (get array 'vec) index val))
- (set! index (+ index (* (list-ref refs i) product)))
- (set! product (* product (list-ref dimensions i)))))
- ((= (length refs) rank)
- (error "Array subscript out of bounds:" refs dimensions))
- (#t (error "Array reference not same rank as array:" refs rank)))))
-
- ;;;takes an nxm list and returns an nxm array (n is rows, m is columns)
- (define (array! . args)
- (let* ((dim-n (length args))
- (dim-m (length (car args)))
- (outarr (make-array dim-n dim-m 0.0)))
- (do ((i 0 (+ i 1))
- (rows args (cdr rows))
- (row (car args)))
- ((>= i dim-n) outarr)
- (set! row (car rows))
- (do ((j 0 (+ j 1)))
- ((>= j dim-m))
- (array-set! outarr i j (list-ref row j))))))
-
- ;;;takes an list and returns an 1D array
- (define (oneDarray! . args)
- (let* ((dim-n (length args))
- (outarr (make-array dim-n 0.0)))
- (do ((i 0 (+ i 1))
- (thing args (cdr thing)))
- ((>= i dim-n) outarr)
- (array-set! outarr i (car thing)))))
-
- ;;;copy-array takes a source array and copies it to a new,congruent
- ;;;(same number of rows and columns) destination array
- (define (copy-array source)
- (let* ((dimss (get source 'dims))
- (destination (apply make-array (append dimss (list 0.0))))
- (vecs (get source 'vec))
- (vecd (get destination 'vec)))
- (do ((i 0 (+ i 1))
- (len (vector-length vecs)))
- ((>= i len))
- (vector-set! vecd i (vector-ref vecs i)))
- (put destination 'newdims (get source 'newdims))
- (put destination 'offsets (get source 'offsets))
- destination))
-
- (define (transpose array)
- (let ((dim (get array 'dims))
- (rank (get array 'rank)))
- (case rank
- ((1)
- (do ((i 0 (+ i 1))
- (result (make-array 1 (car dim) 0.0)))
- ((>= i (car dim)) result)
- (array-set! result 0 i (array-ref array i))))
- ((2)
- (do ((i 0 (+ i 1))
- (result (make-array (cadr dim) (car dim) 0.0)))
- ((>= i (car dim)) result)
- (do ((j 0 (+ j 1)))
- ((>= j (cadr dim)))
- (array-set! result j i (array-ref array i j)))))
- (else (error "transpose can't do rank" rank)))))
-
- (define (array-norm arr lastp)
- (let* ((rank (get arr 'rank))
- (dim1 (car (get arr 'newdims))))
- (if lastp #t (set! dim1 (- dim1 1)))
- (case rank
- ((1) (do ((i 0 (+ i 1))
- (accum 0))
- ((>= i dim1) (sqrt accum))
- (set! accum (+ accum (* (array-ref arr i) (array-ref arr i))))))
- (else (error "can't do norm of rank:" rank)))))
-
- ;;;Normalize normalizes a vector in place(!): returns the vector
- ;;;of magnitude 1.0; lastp allows the last (homogeneous) coord to be ignored
- (define (normalize vec lastp)
- (let* ((dim1 (car (get vec 'dims)))
- (norm (array-norm vec lastp)))
- (if lastp #t (set! dim1 (- dim1 1)))
- (do ((i 0 (+ i 1)))
- ((>= i dim1) vec)
- (array-set! vec i (/ (array-ref vec i) norm)))))
-
- ;;;scalar-mult returns a new array which is the source array * num
- (define (scalar-mult num arr)
- (let* ((dims (get arr 'dims))
- (newarr (copy-array arr)))
- (do ((i 0 (+ i 1))
- (vec (get newarr 'vec)))
- ((>= i (vector-length vec)) newarr)
- (vector-set! vec i (* num (vector-ref vec i))))))
-
- (define (cross-product vec1 vec2)
- (if (and (>= (car (get vec1 'dims)) 3) (>= (car (get vec2 'dims)) 3))
- (let ((outarr (make-array 3 0.0)))
- (array-set! outarr 0 (- (* (array-ref vec1 1) (array-ref vec2 2))
- (* (array-ref vec1 2) (array-ref vec2 1))))
- (array-set! outarr 1 (- (* (array-ref vec1 2) (array-ref vec2 0))
- (* (array-ref vec1 0) (array-ref vec2 2))))
- (array-set! outarr 2 (- (* (array-ref vec1 0) (array-ref vec2 1))
- (* (array-ref vec1 1) (array-ref vec2 0))))
- outarr)
- (error "Non-3D vector passed to cross-product:" vec1 vec2)))
-
- (define (dot-product vec1 vec2)
- (let* ((dim1 (car (get vec1 'newdims)))
- (dim2 (car (get vec2 'newdims))))
- (if (= dim1 dim2)
- (do ((i 0 (+ i 1))
- (accum 0.0))
- ((>= i dim1) (make-array 1 accum))
- (set! accum (+ accum (* (array-ref vec1 i) (array-ref vec2 i))))))))
-
-
- ;;;multiplies a 1-dimensional array times a two-dimensional array
- ;;;(here we call a 1-dim array a vector although it's not)
- ;;;it returns a 1D array
- (define (vecarrmult vector array)
- (let* ((dim1 (get array 'newdims))
- (dim2 (car (get vector 'newdims)))
- (vec (get vector 'vec))
- (a (get array 'vec))
- (destination (make-array (cadr dim1) 0.0)))
- (if (= (car dim1) dim2)
- (do ((i 0 (+ i 1))
- (sum 0 0))
- ((>= i (cadr dim1)))
- (do ((j 0 (+ 1 j)))
- ((>= j dim2))
- (set! sum (+ sum (* (array-ref array j i) (vector-ref vec j)))))
- (array-set! destination i sum))
- (error "Non-matching array dim, vector passed to vecarrmult:"
- dim1 dim2))
- destination))
-
- ;;;this guy actually multiplies a vector times a 2D array and
- ;;;returns a vector result
- (define (vecarraymult vector array)
- (let* ((dim1 (get array 'newdims))
- (dim2 (vector-length vector))
- (a (get array 'vec))
- (destination (make-vector (cadr dim1) 0.0)))
- (if (= (car dim1) dim2)
- (do ((i 0 (+ i 1))
- (sum 0 0))
- ((>= i (cadr dim1)))
- (do ((j 0 (+ j 1)))
- ((>= j (car dim1)))
- (set! sum (+ sum (* (array-ref array j i) (vector-ref vector j)))))
- (vector-set! destination i sum))
- (error "Non-matching array dim, vector passed to vecarraymult:"
- dim1 dim2))
- destination))
-
- (define (array-product arr1 arr2)
- (let* ((dim1 (get arr1 'newdims))
- (dim2 (get arr2 'newdims))
- (len1 (length dim1))
- (len2 (length dim2))
- (d11 (car dim1))
- (d12 (if (= len1 1) 1 (cadr dim1)))
- (d21 (car dim2))
- (d22 (if (= len2 1) 1 (cadr dim2)))
- (destination (make-array d11 d22 1.0)))
- (if (= d12 d21)
- (do ((i 0 (+ 1 i)))
- ((>= i d11))
- (do ((k 0 (+ 1 k))
- (sum 0 0))
- ((>= k d22))
- (do ((j 0 (+ 1 j))
- (temp 0.0))
- ((>= j d12))
- (if (= len2 1) (set! temp (array-ref arr2 k))
- (set! temp (array-ref arr2 j k)))
- (set! sum (+ sum (* (array-ref arr1 i j) temp))))
- (array-set! destination i k sum)))
- (error "Non-matching array dimensions passed to array-product:"
- dim1 dim2))
- destination))
-
- (define (tensor-product array tensor)
- (let* ((dim1 (get array 'newdims))
- (dim2 (get tensor 'newdims))
- (d11 (car dim1))
- (d12 (cadr dim1))
- (d21 (car dim2))
- (d22 (cadr dim2))
- (d23 (caddr dim2))
- (destination (make-array d11 d22 d23 1.0)))
- (if (= d12 d21)
- (do ((i 0 (+ 1 i)))
- ((>= i d11))
- (do ((k 0 (+ 1 k))
- (sum 0 0)
- (sumarray (make-array d23 0.0) (make-array d23 0.0)))
- ((>= k d22))
- (do ((j 0 (+ 1 j)))
- ((>= j d12))
- (do ((l 0 (+ l 1)))
- ((>= l d23))
- (array-set! sumarray l
- (+ (array-ref sumarray l)
- (* (array-ref array i j)
- (array-ref tensor j k l))))))
- (do ((l 0 (+ l 1)))
- ((>= l d23))
- (array-set! destination i k l (array-ref sumarray l)))))
- (error "Non-matching array dimensions passed to tensor-product:"
- dim1 dim2))
- destination))
-
- (define (tensor-product2 tensor tarray)
- (let* ((dim1 (get tarray 'newdims))
- (dim2 (get tensor 'newdims))
- (d21 (car dim1))
- (d22 (cadr dim1))
- (d11 (car dim2))
- (d12 (cadr dim2))
- (d13 (caddr dim2))
- (destination (make-array d11 d22 d13 1.0)))
- (if (= d12 d21)
- (do ((i 0 (+ 1 i)))
- ((>= i d11))
- (do ((k 0 (+ 1 k))
- (sum 0 0)
- (sumarray (make-array d13 0.0) (make-array d13 0.0)))
- ((>= k d22))
- (do ((j 0 (+ 1 j)))
- ((>= j d12))
- (do ((l 0 (+ l 1)))
- ((>= l d13))
- (array-set! sumarray l
- (+ (array-ref sumarray l)
- (* (array-ref tensor i j l)
- (array-ref tarray j k))))))
- (do ((l 0 (+ l 1)))
- ((>= l d13))
- (array-set! destination i k l (array-ref sumarray l)))))
- (error "Non-matching array dimensions passed to tensor-product2:"
- dim1 dim2))
- destination))
-
- (define (tensor-partial-transpose tensor)
- (let ((dim (get tensor 'newdims)))
- (do ((i 0 (+ i 1))
- (result (make-array (cadr dim) (car dim) (caddr dim) 0.0)))
- ((>= i (car dim)) result)
- (do ((j 0 (+ j 1)))
- ((>= j (cadr dim)))
- (do ((k 0 (+ k 1)))
- ((>= k (caddr dim)))
- (array-set! result j i k (array-ref tensor i j k)))))))
-
- (define (vectenmult vector tensor)
- (let* ((d1 (car (get vector 'newdims)))
- (tendims (get tensor 'newdims))
- (d21 (car tendims))
- (dest (apply make-array (append (cdr tendims) (list 0.0)))))
- (if (= d1 d21)
- (do ((j 0 (+ j 1)))
- ((>= j (cadr tendims)) dest)
- (do ((i 0 (+ i 1)))
- ((>= i (car tendims)))
- (do ((k 0 (+ k 1)))
- ((>= k (caddr tendims)))
- (array-set! dest j k (+ (* (array-ref vector i)
- (array-ref tensor i j k))
- (array-ref dest j k))))
- ))
- (error "Non-matching indices for vectenmult:" d1 d21))))
-
- (define (point-distance array index1 index2)
- (do ((i 0 (+ i 1))
- (dx 0.0) (onedist 0.0))
- ((>= i 3) (sqrt dx))
- (set! onedist (- (array-ref array index1 i) (array-ref array index2 i)))
- (set! dx (+ dx (* onedist onedist)))))
-
- (define (removit element alist)
- (do ((lesslist alist (cdr lesslist))
- (outlist (list)))
- ((null? lesslist) (reverse outlist))
- (if (equal? element (car lesslist))
- #t
- (set! outlist (cons (car lesslist) outlist)))))
-
- (define (arraymult arr1 arr2)
- (array* arr1 arr2))
-
- ;;;array* multiplies two arrays of appropriate dimension and returns a
- ;;;(new) product array
- (define (array* arr1 arr2)
- (let ((numberp1 (number? arr1))
- (numberp2 (number? arr2)))
- (cond ((and numberp1 numberp2) (* arr1 arr2))
- (numberp1 (scalar-mult arr1 arr2))
- (numberp2 (scalar-mult arr2 arr1))
- (#t
- (let* ((r1 (get arr1 'rank))
- (r2 (get arr2 'rank))
- (dims 0) (newdims 0)
- (out
- (case r1
- ((1)
- (case r2
- ((1) (dot-product arr1 arr2))
- ((2) (vecarrmult arr1 arr2))
- ((3) (vectenmult arr1 arr2))
- (else (error "array* can't do ranks:" r1 r2))))
- ((2)
- (case r2
- ((1 2) (array-product arr1 arr2))
- ((3) (tensor-product arr1 arr2))
- (else (error "array* can't do ranks:" r1 r2))))
- ((3)
- (case r2
- ((1) (error "array* can't do ranks:" r1 r2))
- ((2) (tensor-product2 arr1 arr2))
- (else (error "array* can't do ranks:" r1 r2)))))))
- out)))))
-
- ;;;array- subtracts two congruent arrays and returns a difference array
- (define (array- arr1 arr2)
- (let* ((r1 (get arr1 'rank))
- (r2 (get arr2 'rank))
- (dim1 (get arr1 'newdims))
- (dim2 (get arr2 'newdims))
- (dest (apply make-array (append dim1 (list 0.0)))))
- (if (= r1 r2)
- (if (equal? dim1 dim2)
- (case r1
- ((1) (do ((i 0 (+ i 1)))
- ((>= i (car dim1)) dest)
- (array-set! dest i (- (array-ref arr1 i) (array-ref arr2 i)))))
- ((2) (do ((i 0 (+ i 1)))
- ((>= i (car dim1)) dest)
- (do ((j 0 (+ j 1)))
- ((>= j (cadr dim1)))
- (array-set! dest i j (- (array-ref arr1 i j)
- (array-ref arr2 i j))))))
- (else (error "Can't array- rank:" r1)))
- (error "non-congruent arrays in array-:" dim1 dim2))
- (error "Different rank arrays in array-:" r1 r2))))
-
- ;;;like array-, only adds
- (define (array+ arr1 arr2)
- (let* ((r1 (get arr1 'rank))
- (r2 (get arr2 'rank))
- (dim1 (get arr1 'newdims))
- (dim2 (get arr2 'newdims))
- (dest (apply make-array (append dim1 (list 0.0)))))
- (if (= r1 r2)
- (if (equal? dim1 dim2)
- (case r1
- ((1) (do ((i 0 (+ i 1)))
- ((>= i (car dim1)) dest)
- (array-set! dest i (+ (array-ref arr1 i) (array-ref arr2 i)))))
- ((2) (do ((i 0 (+ i 1)))
- ((>= i (car dim1)) dest)
- (do ((j 0 (+ j 1)))
- ((>= j (cadr dim1)))
- (array-set! dest i j (+ (array-ref arr1 i j)
- (array-ref arr2 i j))))))
- (else (error "Can't array+ rank:" r1)))
- (error "non-congruent arrays in array+:" dim1 dim2))
- (error "Different rank arrays in array+:" r1 r2))))
-
- ;;;;if a dimension is degenerate, crunch it down (reduce rank)
- (define (reduce-rank out)
- (let ((dims (get out 'dims))
- (newdims (get out 'newdims)))
- (set! dims (removit 0 (removit 1 dims)))
- (set! newdims (removit 0 (removit 1 newdims)))
- (put out 'dims dims)
- (put out 'newdims newdims)
- (put out 'rank (length newdims))
- out))
-
-
- (define (print-array arr)
- (let* ((rank (get arr 'rank))
- (dims (get arr 'newdims))
- (columns (if (not (null? dims)) (car dims))))
- (cond ((= rank 0)
- (format #t "|~s|~%" (vector-ref (get arr 'vec) 0)))
- ((= rank 1)
- (format #t "|")
- (do ((j 0 (+ j 1)))
- ((>= j columns))
- (format #t "~7 " (array-ref arr j)))
- (format #t "|~%"))
- ((= rank 2)
- (do ((j 0 (+ j 1))
- (rows (cadr dims)))
- ((>= j columns))
- (format #t "|")
- (do ((i 0 (+ i 1)))
- ((>= i rows))
- (format #t "~7 " (array-ref arr j i)))
- (format #t "|~%")))
- ((= rank 3)
- (do ((j 0 (+ j 1))
- (rows (cadr dims))
- (third (caddr dims)))
- ((>= j columns))
- (format #t "|")
- (do ((k 0 (+ k 1)))
- ((>= k third))
- (format #t " |")
- (do ((i 0 (+ i 1)))
- ((>= i rows))
- (format #t "~7 " (array-ref arr j i k)))
- (format #t "|"))
- (format #t "|~%")))
- (else (error "Don't know how to print array of rank" rank)))
- arr))
-
- (define (print-array-partial . args)
- (let* ((arr (car args))
- (limits (cdr args))
- (rank (get arr 'rank))
- (dims (get arr 'newdims))
- (columns (if (not (null? dims)) (car dims))))
- (cond ((not (= (length limits) rank))
- (error "limits not equal to rank of array" limits rank))
- ((= rank 0)
- (format #t "|~s|~%" (vector-ref (get arr 'vec) 0)))
- ((= rank 1)
- (format #t "|")
- (do ((j (caar limits) (+ j 1)))
- ((> j (cadar limits)))
- (format #t "~7 " (array-ref arr j)))
- (format #t "|~%"))
- ((= rank 2)
- (do ((j (caar limits) (+ j 1))
- (rows (cadr dims)))
- ((> j (cadar limits)))
- (format #t "|")
- (do ((i (car (cadr limits)) (+ i 1)))
- ((> i (cadr (cadr limits))))
- (format #t "~7 " (array-ref arr j i)))
- (format #t "|~%")))
- ((= rank 3)
- (do ((j (caar limits) (+ j 1))
- (rows (cadr dims))
- (third (caddr dims)))
- ((> j (cadar limits)))
- (format #t "|")
- (do ((k (car (cadr limits)) (+ k 1)))
- ((> k (cadr (cadr limits))))
- (format #t " |")
- (do ((i (car (caddr limits)) (+ i 1)))
- ((> i (cadr (caddr limits))))
- (format #t "~7 " (array-ref arr j i k)))
- (format #t "|"))
- (format #t "|~%")))
- (else (error "Don't know how to print array of rank" rank)))
- arr))
-
- (define (identity-matrix . args)
- (let* ((dims (or (and (not (null? args)) (car args)) 4))
- (mat (make-array dims dims 0.0)))
- (do ((i 0 (+ i 1)))
- ((>= i dims) mat)
- (array-set! mat i i 1.0))))
-
- (define (yaw mat angle)
- (let ((yawmat (make-array 4 4 0.0))
- (cosa (cos (degrees-to-radians angle)))
- (sina (sin (degrees-to-radians angle))))
- (array-set! yawmat 0 0 cosa)
- (array-set! yawmat 0 1 (- sina))
- (array-set! yawmat 1 0 sina)
- (array-set! yawmat 1 1 cosa)
- (array-set! yawmat 2 2 1.0)
- (array-set! yawmat 3 3 1.0)
- (arraymult mat yawmat)))
-
- (define (pitch mat angle)
- (let ((pitchmat (make-array 4 4 0.0))
- (cosa (cos (degrees-to-radians angle)))
- (sina (sin (degrees-to-radians angle))))
- (array-set! pitchmat 0 0 cosa)
- (array-set! pitchmat 0 2 sina)
- (array-set! pitchmat 2 0 (- sina))
- (array-set! pitchmat 2 2 cosa)
- (array-set! pitchmat 1 1 1.0)
- (array-set! pitchmat 3 3 1.0)
- (arraymult mat pitchmat)))
-
- (define (roll mat angle)
- (let ((rollmat (make-array 4 4 0.0))
- (cosa (cos (degrees-to-radians angle)))
- (sina (sin (degrees-to-radians angle))))
- (array-set! rollmat 2 2 cosa)
- (array-set! rollmat 1 1 cosa)
- (array-set! rollmat 1 2 (- sina))
- (array-set! rollmat 2 1 sina)
- (array-set! rollmat 0 0 1.0)
- (array-set! rollmat 3 3 1.0)
- (arraymult mat rollmat)))
-
- (define (rotation-matrix-about-vector vector angle)
- (let* ((mat (make-array 4 4 0.0))
- (mag (list-magnitude vector))
- (n1 (/ (car vector) mag))
- (n2 (/ (cadr vector) mag))
- (n3 (/ (caddr vector) mag))
- (cosa (cos angle))
- (sina (sin angle)))
- (array-set! mat 0 0 (+ (* n1 n1) (* (- 1 (* n1 n1)) cosa)))
- (array-set! mat 0 1 (+ (* n1 n2 (- 1 cosa)) (* n3 sina)))
- (array-set! mat 0 2 (- (* n1 n3 (- 1 cosa)) (* n2 sina)))
- (array-set! mat 1 0 (- (* n1 n2 (- 1 cosa)) (* n3 sina)))
- (array-set! mat 1 1 (+ (* n2 n2) (* (- 1 (* n2 n2)) cosa)))
- (array-set! mat 1 2 (+ (* n2 n3 (- 1 cosa)) (* n1 sina)))
- (array-set! mat 2 0 (+ (* n1 n3 (- 1 cosa)) (* n2 sina)))
- (array-set! mat 2 1 (- (* n2 n3 (- 1 cosa)) (* n1 sina)))
- (array-set! mat 2 2 (+ (* n3 n3) (* (- 1 (* n3 n3)) cosa)))
- (array-set! mat 3 3 1.0)
- mat))
-
- (define (translate mat x y z)
- (array-set! mat 3 0 (+ (array-ref mat 3 0) x))
- (array-set! mat 3 1 (+ (array-ref mat 3 1) y))
- (array-set! mat 3 2 (+ (array-ref mat 3 2) z))
- mat)
-
- (define (arr-extrema array1)
- (let* ((dims (get array1 'dims))
- (dim1 (car dims))
- (dim2 (cadr dims)))
- (do ((ind 0 (+ ind 1))
- (extremes (do ((i 0 (+ i 1))
- (vec (make-vector (* 2 dim2) -1.e300)))
- ((>= i dim2) vec)
- (vector-set! vec i 1.e300))))
- ((>= ind dim1) extremes)
- (do ((i 0 (+ i 1)))
- ((>= i dim2))
- (if (< (array-ref array1 ind i) (vector-ref extremes i))
- (vector-set! extremes i (array-ref array1 ind i)))
- (if (> (array-ref array1 ind i) (vector-ref extremes (+ i dim2)))
- (vector-set! extremes (+ i dim2) (array-ref array1 ind i)))))))
-
- (define (average-arr-extrema extvec)
- (let ((halflen (integer-coerce (/ (vector-length extvec) 2))))
- (do ((i 0 (+ i 1))
- (outlist (list)))
- ((>= i halflen) (reverse outlist))
- (set! outlist (cons (/ (+ (vector-ref extvec i)
- (vector-ref extvec (+ i halflen)))
- 2)
- outlist)))))
-
-
- (define *effector* '(0.0 0.0 0.0 0.0 0.0 0.0))
-
- (define *inv-effector-transform* (list))
-
-
- ;;; Given a non-singular matrix arr1, returns a new inverse matrix of the same
- ;;; dimension. The values in array arr1 will be destroyed by the inversion
- ;;; algorithm. It is an error if the matrix is not square.
-
- (define (arrayinvert arr1)
- (let* ((adim (get arr1 'dims))
- (dim (car adim))
- (odim (cadr adim)))
- (if (= dim odim)
- (let ((arr2 (identity-matrix dim))) ;; set up arr2 as identity matrix.
-
- (do ((diag 0 (+ diag 1))
- (amax -1.0)
- (imax 0))
- ((>= diag dim))
-
- ;; find the maximal element in column diag.
- (do ((i 0 (+ i 1))
- (adiag 0))
- ((>= i dim))
- (set! adiag (abs (array-ref arr1 i diag)))
- (if (>= adiag amax)
- (begin
- (set! amax adiag)
- (set! imax i))))
-
- ;; swap row diag with the row containing the maximal element.
- (do ((j 0 (+ j 1))
- (tmp 0.0))
- ((>= j dim))
- (set! tmp (array-ref arr1 imax j))
- (array-set! arr1 imax j (array-ref arr1 diag j))
- (array-set! arr1 diag j tmp)
- (set! tmp (array-ref arr2 imax j))
- (array-set! arr2 imax j (array-ref arr2 diag j))
- (array-set! arr2 diag j tmp))
-
- ;; scale row diag so that the value of the diagonal element is 1.0.
- (do ((j 0 (+ j 1))
- (s (/ 1.0 (array-ref arr1 diag diag))))
- ((>= j dim))
- (array-set! arr1 diag j (* (array-ref arr1 diag j) s))
- (array-set! arr2 diag j (* (array-ref arr2 diag j) s)))
-
- ;; clear out the column above and below diagonal diag.
- (do ((i 0 (+ i 1))
- (return #f)
- (s 0.0))
- ((or return (>= i dim)))
- (if (= i diag)
- (set! return #t)
- (begin
- (set! s (array-ref arr1 i diag))
- (do ((j 0 (+ j 1)))
- ((>= j dim))
- (array-set! arr1 i j (- (array-ref arr1 i j)
- (* s (array-ref arr1 diag j))))
- (array-set! arr2 i j (- (array-ref arr2 i j)
- (* s (array-ref arr2 diag j)))))))))
- arr2
- )
- (error "A matrix passed to arrayinvert must be square:" dim dim0)
- ))
- )
-